﻿using ArtMath.Attribute;
using ArtMath.Component.Interface;
using ArtMath.Component;
using System;
using System.ComponentModel;
using ArtMath.Core.Helper;
using ArtMath.Resource;
using ArtMath.CommonType;

namespace ArtMath.Parameter
{
    /// <summary>
    /// 两直线到角
    /// </summary>
    [Serializable]
    public class TwoStraightLinesArrivalAngleParameter : CalculatedParameter
    {
        int round;
        bool saveRound;
        IDirectedAngle init, term;
        public TwoStraightLinesArrivalAngleParameter(SketchPad pad, string name, IDirectedAngle start, IDirectedAngle end, bool saveRound) : base(pad, name, ToolTypeName.lzxdj)
        {
            Unit = ParameterUnit.Radian;
            InitialEdge = start;
            TerminalEdge = end;
            SaveRound = saveRound;
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("InitialEdge")]
        public IDirectedAngle InitialEdge
        {
            get { return init; }
            set
            {
                if (init is object)
                {
                    init.CalculatedParameters.Remove(this);
                }
                init = value;
                if (init is object)
                {
                    init.CalculatedParameters.Add(this);
                    Value.SetExpression(GetNewValue());
                }
            }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("TerminalEdge")]
        public IDirectedAngle TerminalEdge
        {
            get { return term; }
            set
            {
                if (term is object)
                {
                    term.CalculatedParameters.Remove(this);
                }
                term = value;
                if (term is object)
                {
                    term.CalculatedParameters.Add(this);
                    Value.SetExpression(GetNewValue());
                }
            }
        }
        [MultilingualCategory("Structure"), DefaultValue(typeof(bool), "False"), MultilingualDisplayName(null, "Save", "ParaRound"), TypeConverter(typeof(ArtMath.Converter.BooleanConverter))]
        public bool SaveRound
        {
            get { return saveRound; }
            set
            {
                saveRound = value;
                Value.SetExpression(GetNewValue());
            }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("ParaRound"), ReadOnly(true)]
        public int Round
        {
            get { return round; }
            set
            {
                round = value;
                Value.SetExpression(GetNewValue());
            }
        }
        public override bool CanRecover
        {
            get
            {
                return base.CanRecover && InitialEdge.ObjectState == ObjectState.Normal && TerminalEdge.ObjectState == ObjectState.Normal;
            }
        }
        public override void Delete(bool recoverable = false)
        {
            base.Delete(recoverable);
            if (recoverable)
            {

            }
            else
            {
                InitialEdge = null;
                TerminalEdge = null;
            }
        }
        public override void Recover()
        {
            if (InitialEdge.ObjectState != ObjectState.Normal)
            {
                throw new ObjectDisposedException(InitialEdge.Name, string.Format(Resources.Translate("CannotFindObject"), InitialEdge.Name));
            }
            if (TerminalEdge.ObjectState != ObjectState.Normal)
            {
                throw new ObjectDisposedException(TerminalEdge.Name, string.Format(Resources.Translate("CannotFindObject"), TerminalEdge.Name));
            }
            base.Recover();
        }
        public override double GetNewValue()
        {
            if (InitialEdge == null || TerminalEdge == null)
            {
                return 0;
            }
            double nowV = Angle.StandardizeRad(TerminalEdge.NewDirectedAngle - (InitialEdge == null ? 0 : InitialEdge.NewDirectedAngle));
            if (SaveRound)
            {
                double oldV = Angle.StandardizeRad(Value.Value);
                if (Utility.CrossProduct(Utility.GetUnitVector(oldV), Utility.GetUnitVector(nowV)) > 0)
                {
                    if (nowV < oldV)
                    {
                        round++;
                    }
                }
                else
                {
                    if (nowV > oldV)
                    {
                        round--;
                    }
                }
                return round * Angle.RadRound + nowV;
            }
            else
            {
                return nowV;
            }
        }
    }
}
